#pragma once
#include "UIProperty.h"
#include "UITimerTask.h"

#define ANIMATION_FRAMES_PER_SECOND	24

namespace DirectUI
{
	namespace UIAnimation
	{
		enum UIAnimationProperytyName
		{
			Name,
			AutoReverse,
			BeginTime,
			Duration,
			From_Double,
			To_Double,
			By_Double,
			From_Color,
			To_Color,
			By_Color,
			TargetName,
			TargetProperty,
			UIANIMATIONPROPERYTYNAMEMAX,
		};

		interface __declspec(uuid("E31C3FF3-1C48-44A3-B120-2A40409D6B1C")) IUITimeline : public IUIObject, public IUIPropertyEvent
		{
			virtual IUIProperty*	GetProperty(LPCTSTR lpName) = 0;
			virtual IUIProperty*	GetProperty(UIAnimationProperytyName name) = 0;
			virtual	void			ParseAttribute(LPCTSTR lpszAttr) = 0;
			virtual UITIMESPAN		GetTimerSpan() = 0;
		};

		interface __declspec(uuid("6EB53D27-7026-4408-8B27-173B24F4324E")) IUIStoryboard : public IUITimeline
		{
			virtual void	AddChild(IUITimeline* lpChild) = 0;
			virtual	void	Begin(IUIElement* lpStateOwner) = 0;
			virtual	void	Stop() = 0;
		};

		interface __declspec(uuid("F3F744E4-B072-4330-9120-67878D5EC307")) IUIDoubleAnimation : public IUITimeline
		{
		}; 

		interface __declspec(uuid("D04AEAF0-F29B-43C1-8484-6D56241C58D1")) IUIColorAnimation : public IUITimeline
		{
		}; 

		
		IUIElement*	GetElementTemplateObject();

		template <
			typename baseclass,
			typename classname, 
			typename interfacename>
		class CUITimeline
			: public CUINoAggregateObjectImplHelper<baseclass, classname, interfacename>
		{
			DECLARE_CLASS(CUITimeline, Timeline)
		private:
			BEGIN_UI_PROPERTY_MAP(UIAnimationProperytyName)
				UI_PROPERTY(Name, ot_string)
				UI_PROPERTY(AutoReverse, ot_bool)
				UI_PROPERTY(BeginTime, ot_int64)
				UI_PROPERTY(Duration, ot_int64)
				UI_PROPERTY(From_Double, ot_double)
				UI_PROPERTY(To_Double, ot_double)
				UI_PROPERTY(By_Double, ot_double)
				UI_PROPERTY(From_Color, ot_int32)
				UI_PROPERTY(To_Color, ot_int32)
				UI_PROPERTY(By_Color, ot_int32)
				UI_PROPERTY(TargetName, ot_string)
				UI_PROPERTY(TargetProperty, ot_int32)
			END_UI_PROPERTY_MAP
		public:
			
			CUITimeline(void)
			{
				ProperyInfoInit();
			}

			virtual ~CUITimeline(void)
			{
			}

			virtual UITIMESPAN GetTimerSpan() { return (UITIMESPAN)(1000.0/ANIMATION_FRAMES_PER_SECOND); }
			virtual void Animate(IUIElement* lpOwnerElement) { }
			virtual void StopAnimate() { }

			virtual	void ParseAttribute(LPCTSTR lpszAttr)
			{
				xml_document doc;
				if ( !doc.load(lpszAttr) )
					return;

				xml_node node = doc.first_child();
				OnBeforeParseAttribute(node);
				xml_node::attribute_iterator it = node.attributes_begin();
				while ( it != node.attributes_end() )
				{
					xml_attribute attr = *it;
					OnParseAttribute(attr, NULL);
					++it;
				}
			}

			virtual void		OnBeforeParseAttribute(xml_node& node) { }

			virtual void		OnParseAttribute(xml_attribute& attr, LPCTSTR lpAttrAlias)
			{
				CString szAttrName = lpAttrAlias;
				if ( szAttrName.IsEmpty() )
					szAttrName = attr.name();
				CString szVal = attr.value();
				if ( szAttrName.CollateNoCase(_T("TargetProperty")) == 0 )
				{
					int e;
					if ( !GetElementTemplateObject()->GetUIElementNameEnum(szVal, e) )
					{
						assert(false);
						return;
					}
					CUIObjectPtr<IUIProperty> spProperty = GetProperty(szAttrName);
					if ( spProperty ) spProperty->SetIntValue(e);
					return;
				}

				CUIProperty::TimelineParseAttribute(attr, GetProperty(szAttrName));
			}

			virtual HRESULT QueryInterface( const GUID& guid, void** lppObject ) 
			{
				if ( guid == __uuidof(IUITimeline) )
				{
					if (lppObject)
					{
						*lppObject = (IUITimeline*)this;
						AddRef();
					}
					return S_OK;
				}
				else if ( guid == __uuidof(IUIPropertyEvent) )
				{
					if (lppObject)
					{
						*lppObject = (IUIPropertyEvent*)this;
						AddRef();
					}
					return S_OK;
				}

				return __super::QueryInterface(guid, lppObject);
			}

			virtual	void		PropertyChanged(int PropertyNameEnum) { }
		};

		class CUIStoryboard : public CUITimeline<IUIStoryboard, CUIStoryboard, IUIStoryboard>
		{
		public:
			DECLARE_CLASS(CUIStoryboard, Storyboard)
		public:
			CUIStoryboard ();
			~CUIStoryboard ();

			virtual void	Begin(IUIElement* lpStateOwner);
			virtual void	Stop();

			virtual void	AddChild(IUITimeline* lpChild);
			virtual HRESULT QueryInterface( const GUID& guid, void** lppObject );

		private:
			std::vector<CUIObjectPtr<IUITimeline>>	m_vChildrens;
		};

		
	}
}
